home *** CD-ROM | disk | FTP | other *** search
- { SPX Library Version 3.0 Copyright 1993 Scott D. Ramsay }
-
- The SPX_SND units it the direct sound unit. It allows
- the playing of digital sound through a Sound Blaster compatible card,
- a DAC device on the LPT port (Covox), or the PC speaker.
- It also maintains eight clock timers to use for game precision.
-
- s_clk : array[0..3] of word; { slow counters }
- f_clk : array[0..3] of word; { fase counters }
-
- The unit takes control of the computer's clock interrupt and allows
- the changing of its interrupt frequency. From its regular 18.2 times per
- second.
-
- The slow counters always count down at 18.2 times a second. Regardless of
- the clock interrupt's rate. So, for example, the loop below will wait
- for 5 seconds:
-
- s_clk[0] := 5*18;
- repeat
- until s_clk[0]=0;
-
- Notice that there is nothing in the repeat loop. The counters are
- automatically decremented. The counter also do not roll over. They will
- decrement until they reach zero then stop.
-
- The fast counters count down according to the clock rate. The clock rate
- can be changed by the following procedure:
-
- procedure setrate(cycles:word);
-
- The variable cycles indicates the number of cycles(interrupts) to generate
- per second. So setrate(18); will restore the clock to its original rate.
- Setrate(1000); will generate an interrupt 1000 times per second. Warning some
- slow computers (8086/286) can not handle high clock rates. Also conflicts
- may occur if running under MS Windows or OS/2.
-
- Here's another example:
-
- setrate(2048); { set the clock rate }
- f_clk[0] := 4096;
- repeat
- until f_clk[0]=0;
-
- The above example will loop for 2 seconds.
-
- A nice thing about the counters is that you can use them to
- regulate the speed of your program/game. Lets make a VERY rough
- example. Lets suppose you wrote a game that you want each 'frame'
- or pass to take 1 second. Your game loop would look something
- like this:
-
- repeat
- s_clk[0] := 18;
- { grab user inputs }
- { do game calcuations }
- { setup objects for display }
- { update visual screen }
- while s_clk[0]<>0 do;
- until game_over;
-
- If one pass of the loop is faster than one second, then the game
- will wait in the while loop until a second it up. Now depending on the
- speed of the computer, the number of calcuations, speed of displaying the
- sprites, the wait time may vary. But the above loop will always wait
- at MOST one second. Now if one pass takes longer than a second then the
- counter is already reached zero so there is no delay. So the loop is
- running at maximum speed.
-
- Now the event loops for games tend to run alot faster than 1 sec. So
- we would use a fast clock counter.
-
- setrate(3000);
- repeat
- f_clk[0] := 80;
- { grab user inputs }
- { do game calcuations }
- { setup objects for display }
- { update visual screen }
- while f_clk[0]<>0 do;
- until game_over;
-
- Now were all set. We can even get fancy. We can even automatically
- adjust the rate according to the cabilities of the machine;
-
- var
- crate : word;
-
- setrate(3000);
- crate := 80;
- repeat
- f_clk[0] := crate;
- { grab user inputs }
- { do game calcuations }
- { setup objects for display }
- { update visual screen }
- if (crate>0) and (f_clk[0]<10)
- then dec(crate);
- while f_clk[0]<>0 do;
- until game_over;
-
- Now if the computer can't keep up with the rate (The clock comes
- close to timing out). The rate is speeded up.
-
-
- The unit uses the variable clock speeds for the playing of
- the audio. To play an audio segment, the unit sets the clock rate
- to the sample rate of the sound. Then at each interrupt it outputs
- a sample byte to directed sound port.
-
- Here are some ports you can use.
-
- $42 - PC speaker
- $378 - LPT1 sound devices such as Covox
- $210-$260 - Sound Blaster compatible cards
-
- Here's how to play an 8khz raw sound file:
-
- Uses SPX_SND;
-
- var
- sound : Tsound;
- begin
- setrate(8192); { Set clock to sound sample }
- sound.init('Mysound.raw',$42,false); { load the sound, use PC speaker }
- sound.play(true); { play the sound }
- repeat until not playing; { wait for completion }
- sound.done; { do cleanup }
- end.
-
-
- NOTES:
- This unit will not work in protected mode because of changing the clock
- rate. As a result the the f_clk counters will act as s_clk counters. Such
- in a Windows DOS box. etc.
- ───────────────────────────────────────────────────────────────────────────
- GLOBAL VARIABLES:
-
- cs: Can stop flag, FALSE - if the current audio playing
- does not want to be interupted
- playing: TRUE - if a sound is currently playing
- f_clk: Fast clock counters
- s_clk: Slow clock counters
- rate: Current fast clock rate
- cntime: Reserved counter, Do not modify
- --------------------------------------------------------
- f_userclk,
- s_userclk : userproc;
-
- F_USERCLK and S_USERCLK allows you to add your own custom routines
- at each clock interrupt. Since these procedures are called at every
- interrupt you have to avoid a few things:
-
- 1. You routine should be fast as possible. Since it will be called
- many times. if it does to many calculations, it will slow the
- program down.
-
- 2. Do not call any interupts. You are already in one.
-
- 3. Avoid disk access. It may or may not work. Don't try it!
-
- 4. Your routine must be declared as a far procedure with no
- parameters.
-
- Example:
-
- Uses spx_tim;
-
- var
- l,s : longint;
-
- procedure MyUserClk; far;
- begin
- inc(l);
- end;
-
-
- begin
- l := 0;
- s_userclk := MyUserClk;
- readln; s := l;
- writeln('My function was called ',s,' times while waiting');
- end.
-
-
- ───────────────────────────────────────────────────────────────────────────
- type
- Psound = ^Tsound;
- Tsound = object
-
- Base sound object. Used for playing digitized sound.
-
- VARIABLES:
- sblk:pointer Buffer to the sound data;
- size:word Size of sound buffer;
- sport:word Port address for sound;
- sb_play:boolean Set to TRUE if (sport) is a sound blaster
- port
-
- METHODS:
-
- ---------------------------------------------------
- constructor tsound.init(sndfile:string;prt:word;_sb:boolean);
-
- Sets up the sound object. By loading the the sound file
-
- SNDFILE: DOS file name of raw sound file;
- PRT: Sound port to use for the object;
- _SB: Set to TRUE if PRT is a sound blaster port
-
-
- ---------------------------------------------------
- function tsound.loadsnd(sndfile:string;prt:word;_sb:boolean):boolean; virtual;
-
- Load a raw sound file into the object.
-
- SNDFILE: DOS file name of the raw sound file;
- PRT: Sound port to use for the object;
- _SB: Set to TRUE if PRT is a Sound Blaster port
-
- ---------------------------------------------------
- function tsound.filesnd(var fil:file;bsize,prt:word;_sb:boolean):boolean; virtual;
-
- Loads a data from an open file.
-
- FIL: File that contains sound data;
- BSIZE: Size of sound data in file;
- PRT: Sound port to use for the object;
- _SB: Set to TRUE if PRT is a Sound Blaster port
-
- NOTE: Does not close file
-
- ---------------------------------------------------
- procedure tsound.cleansnd; virtual;
-
- Deallocates heap memory space for the sound.
-
- ---------------------------------------------------
- procedure tsound.play(canstop:boolean); virtual;
-
- Plays the sound.
-
- CANSTOP: Set to TRUE is allow other sounds to
- interrupt its playing.
-
- ---------------------------------------------------
- procedure tsound.stop; virtual;
-
- Stop the playing of the sound.
-
- ---------------------------------------------------
- destructor tsound.done; virtual;
-
- Preforms and deallocation of the object;
-
- ───────────────────────────────────────────────────────────────────────────
- type
- PEmsSound = ^TEmsSound;
- TEmsSound = object(Tsound)
-
- Expanded memory sound object. Used for playing digitized sound. Stores
- the sound in expanded memory.
-
- VARIABLES:
-
- EMSseg: Segment address of EMS window
- handle: Handle to the ems memory block
- EMSok: Status of the EMS block, TRUE if okay
-
- METHODS:
-
- ---------------------------------------------------
- constructor TEmsSound.init(sndfile:string;prt:word;_sb:boolean);
-
- Sets up the sound object. By loading the the sound file
-
- SNDFILE: DOS file name of raw sound file;
- PRT: Sound port to use for the object;
- _SB: Set to TRUE if PRT is a sound blaster port
-
- ---------------------------------------------------
- function TEmsSound.loadsnd(sndfile:string;prt:word;_sb:boolean):boolean; virtual;
-
- Load a raw sound file into the object.
-
- SNDFILE: DOS file name of the raw sound file;
- PRT: Sound port to use for the object;
- _SB: Set to TRUE if PRT is a Sound Blaster port
-
- ---------------------------------------------------
- procedure TEmsSound.cleansnd; virtual;
-
- Deallocates expanded memory space for the sound.
-
- ---------------------------------------------------
- procedure TEmsSound.play(canstop:boolean); virtual;
-
- Plays the sound.
-
- CANSTOP: Set to TRUE is allow other sounds to
- interrupt its playing.
-
- ---------------------------------------------------
- destructor TEmsSound.done; virtual;
-
- Preforms and deallocation of the object.
-
- ───────────────────────────────────────────────────────────────────────────
- function SBFindBase:word;
-
- Searches for a Sound Blaster compatible card. If found, returns the port
- address of the card. Returns 0 if not found.
-
- ───────────────────────────────────────────────────────────────────────────
- function SBReset(BaseAddr : word) : boolean;
-
- Resets the sound card. Returns TRUE if successful.
-
- BASEADDR: Port address of sound card
-
- ───────────────────────────────────────────────────────────────────────────
- procedure globalstop;
-
- Stops playback of sound.
-
- Note: Same as Tsound.stop and TEmsSound.stop
-
- ───────────────────────────────────────────────────────────────────────────
- procedure setrate(cycles:word);
-
- Changes the clock rate of the computer. Works only in real mode.
-
- CYCLES: Number of interrupts to generate per second
-
- ───────────────────────────────────────────────────────────────────────────
- procedure wait(seconds,which:integer);
-
- Wait for a specified number of seconds.
-
- SECONDS: Number of seconds to wait;
- WHICH: Index number of slow clock counter to use. (0..3)
-
- ───────────────────────────────────────────────────────────────────────────
-